/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package managedbean.FinancialStatus;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
import merlion.common.entity.GlobalVariable;
import merlion.common.session.stateless.GlobalVariableSessionBeanLocal;
import merlion.common.util.Consts;
import merlion.frm.bpm.entity.Invoice;
import merlion.frm.bpm.entity.SupplierInvoice;
import merlion.frm.bpm.pojo.Cash;
import merlion.frm.bpm.pojo.FutureTransaction;
import merlion.frm.bpm.pojo.Payables;
import merlion.frm.bpm.pojo.Receivables;
import merlion.frm.bpm.session.FinancialStatusSessionBeanLocal;

/**
 *
 * @author Kenn
 */
@ManagedBean(name = "fdManagerBean")
@ViewScoped
public class FinancialDashboardManagerBean {
    
    @EJB
    private FinancialStatusSessionBeanLocal fsSessionBean;
    @EJB
    private GlobalVariableSessionBeanLocal gvSessionBean;
    
    private String status;
    private List<String> dangerMonths;
    private GlobalVariable safetyCash;
    private GlobalVariable cashOnHand;
    private Collection<FutureTransaction> transactions;
    private Collection<Receivables> receivables;
    private Collection<Payables> payables;
    private ArrayList<Cash> cash;
    private ArrayList<Timestamp> dates;
    

    public FinancialDashboardManagerBean() {
        
    }
    
    @PostConstruct
    public void init(){
        cashOnHand = gvSessionBean.getGlobalVariableByKey(Consts.GLOBAL_CASH_ON_HAND);
        safetyCash = gvSessionBean.getGlobalVariableByKey(Consts.GLOBAL_SAFETY_CASH);
        generateCash();
    }
    
    private Collection<Receivables> generateReceivables() {
        
        receivables = new ArrayList<Receivables>();
        for (Timestamp ts: dates) {
            Receivables r = new Receivables(ts, transactions);
            receivables.add(r);
        }
        
        return receivables;
    }
    
    private Collection<Payables> generatePayables() {
        
        payables = new ArrayList<Payables>();
        for (Timestamp ts : dates) {
            Payables p = new Payables(ts, transactions);
            payables.add(p);
        }
        
        return payables;
    }
    
    public void refresh(ActionEvent event){
        //UPDATE VARIABLES
        cashOnHand = gvSessionBean.updateGlobalVariable(cashOnHand);
        safetyCash = gvSessionBean.updateGlobalVariable(safetyCash);
        
        generateCash();
    }
    
    private void generateCash(){
        
        dangerMonths = new ArrayList<String>();
        status = "Healthy";
        
        transactions = new ArrayList<FutureTransaction>(getAllFutureTransactions());
        dates = new ArrayList<Timestamp>();
        for (long i = 0; i < 30; i++) {
            long oneDay = (long) (1 * 24 * 60 * 60 * 1000);
            long oneMonth = (long) 30 * oneDay;
            Timestamp t = new Timestamp(System.currentTimeMillis() + (i * oneDay));
            dates.add(t);
        }
        
        // Calculate all
        cash = new ArrayList<Cash>();
        ArrayList<Receivables> rev = new ArrayList<Receivables>(generateReceivables());
        ArrayList<Payables> pay = new ArrayList<Payables>(generatePayables());
        
        for(int i = 0; i < rev.size(); i++){
            
            if(i == 0){
                Cash c = new Cash(cashOnHand.getDoubleValue().doubleValue(), rev.get(i).getAmount(), pay.get(i).getAmount(), dates.get(i));
                cash.add(c);
                if(c.getTotalCash() <= safetyCash.getDoubleValue().doubleValue()){
                    dangerMonths.add(c.getMonth());
                    status = "Poor financial status at the following months: ";
                }
            }
            else {
                Cash c = new Cash(cash.get(i-1).getTotalCash(), rev.get(i).getAmount(), pay.get(i).getAmount(), dates.get(i));
                cash.add(c);
                if(c.getTotalCash() <= safetyCash.getDoubleValue().doubleValue()){
                    dangerMonths.add(c.getMonth());
                    status = "Poor financial status";
                }
            }
        }
        
    }
    
    private Collection<FutureTransaction> getAllFutureTransactions(){
        
        Collection<FutureTransaction> trans = new ArrayList();
        
        ArrayList<SupplierInvoice> siList = new ArrayList<SupplierInvoice>(getAllSupplierInvoices());
        ArrayList<Invoice> iList = new ArrayList<Invoice>(getAllInvoices());
        
        for(Invoice i: iList){
            FutureTransaction t = new FutureTransaction(i);
            trans.add(t);
        }
        for(SupplierInvoice si: siList){
            FutureTransaction t = new FutureTransaction(si);
            trans.add(t);
        }
        
        return trans;
    }
    
    private Collection<SupplierInvoice> getAllSupplierInvoices() {
        return fsSessionBean.getAllUnpaidSupplierInvoice();
    }
    
    private Collection<Invoice> getAllInvoices() {
        return fsSessionBean.getAllUnpaidInvoice();
    }
    
    public String getDummy() {
        return status;
    }

    public void setDummy(String status) {
        this.status = status;
    }

    public ArrayList<Timestamp> getDates() {
        return dates;
    }

    public void setDates(ArrayList<Timestamp> dates) {
        this.dates = dates;
    }

    public Collection<Receivables> getReceivables() {
        return receivables;
    }

    public void setReceivables(Collection<Receivables> receivables) {
        this.receivables = receivables;
    }

    public Collection<FutureTransaction> getTransactions() {
        return transactions;
    }

    public void setTransactions(Collection<FutureTransaction> transactions) {
        this.transactions = transactions;
    }

    public Collection<Payables> getPayables() {
        return payables;
    }

    public void setPayables(Collection<Payables> payables) {
        this.payables = payables;
    }

    public GlobalVariable getCashOnHand() {
        return cashOnHand;
    }

    public void setCashOnHand(GlobalVariable cashOnHand) {
        this.cashOnHand = cashOnHand;
    }

    public List<String> getDangerMonths() {
        return dangerMonths;
    }

    public void setDangerMonths(List<String> dangerMonths) {
        this.dangerMonths = dangerMonths;
    }
    
    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public GlobalVariable getSafetyCash() {
        return safetyCash;
    }

    public void setSafetyCash(GlobalVariable safetyCash) {
        this.safetyCash = safetyCash;
    }

    public ArrayList<Cash> getCash() {
        return cash;
    }

    public void setCash(ArrayList<Cash> cash) {
        this.cash = cash;
    }
    
}
